local skynet = require "skynet"
local socket = require "skynet.socket"
local httpd = require "http.httpd"
local sockethelper = require "http.sockethelper"
local urllib = require "http.url"
local sweb = require "web.sweb"
local lpeg =require "lpeg"
local table = table
local string = string

local config = ...

config = config or {}
local root = config.root or skynet.getenv "root"
local middle_wares = config.middle_wares or {}


local httphandler = {}
httphandler.on_message = function(id,code,url,method,header,body)
	local tmp = {"\n"}
	-- if header.host then
	-- 	table.insert(tmp, string.format("host: %s", header.host))
	-- end
	-- table.insert(tmp, string.format("url: %s", url))
	local path, query = urllib.parse(url)
	-- table.insert(tmp, string.format("path: %s", path))
	if query then
		local q = urllib.parse_query(query)
		for k, v in pairs(q) do
			table.insert(tmp, string.format("query: %s= %s", k,v))
		end
	end
	-- table.insert(tmp, string.format("method: %s", method))
	-- table.insert(tmp, "-----header----")
	-- for k,v in pairs(header) do
	-- 	table.insert(tmp, string.format("%s = %s",k,v))
	-- end
	-- table.insert(tmp, "-----body----\n" .. body)
	skynet.error(table.concat(tmp,"\n"))
end

httphandler.on_error = function(id,code)
	skynet.error("on_error ".. id .. " " .. code)
end

local function response(id, ...)
	local ok, err = httpd.write_response(sockethelper.writefunc(id), ...)

	if ok then
		-- if err == sockethelper.socket_error , that means socket closed.
		-- local code,data = ...
		-- skynet.error(string.format("succeed fd = %d, %d, %s", id, code,data))
	else
		skynet.error(string.format("err fd = %d, %s", id, err))
	end
	return ok,err
end

local function strsplit(pattern, text)
	local list, pos = {}, 1;

	assert(pattern ~= "", "delimiter matches empty string!");

	while true do
		local first, last, match = text:find(pattern, pos);
		if first then -- found?
		list[#list+1] = text:sub(pos, first-1);
		pos = last+1;
		else
		list[#list+1] = text:sub(pos);
		break;
		end
	end

	return list;
end

local function is_static(path)
	local static_regular = config.static_regular or ""
	
	local R, S, V, P = lpeg.R, lpeg.S, lpeg.V, lpeg.P
	local C, Ct, Cmt, Cg, b, Cc = lpeg.C, lpeg.Ct, lpeg.Cmt, lpeg.Cg, lpeg.Cb, lpeg.Cc
	local prefix = P".gif" +
		P".js" +
		P".html" +
		P".css" +
		P".jpeg"
	local t1 = strsplit("|",static_regular)
	if #t1 ==0 then
		t1 = {".js",".html",".css",".jpeg",".pb",".proto"}
	end
	local i,r
	for i,r in ipairs(t1) do
		prefix = prefix + P(r)
	end
	
	local any = (P(1) - P".")^1 
	local uri = P"/" * any * prefix
	-- skynet.error(uri," path ",path," match ",uri:match(path))
	-- if uri:match(path) then
	-- 	return true
	-- else
		return false
	-- end
end

local function open_file(id,file_path)
	-- local root = root
	-- local key = root..file_path
	-- local data 
	-- local cache = skynet.queryservice(SERVICE_NAME)
	-- data = skynet.call(cache,"lua","get",key)
	-- if not data then
	-- 	local file = io.open(key, "rb") 
	-- 	if not file then
	-- 	return response(id,501,"file not exist!")
	-- 	end
	-- 	local size = file:seek("end")  
	-- 	local header = {}
	-- 	header["Content-Length"] = size  
	-- 	file:seek("set", 0)   
	-- 	data = file:read("*a")
	-- 	file:close()  
	-- 	skynet.call(cache,"lua","set",key,data)
	-- end
	skynet.error("httpagent open_file ")
	local data = file_path
	local header ="header"
	response(id,200,data,header)
end


skynet.start(function()
	skynet.dispatch("lua", function (_,_,id)
		-- skynet.error("httpagent start ")
		socket.start(id)
		-- limit request body size to 8192 (you can pass nil to unlimit)
		local code, url, method, header, body = httpd.read_request(sockethelper.readfunc(id), 10240)

		if code then
			if code ~= 200 then
				response(id, code)
			else
				-- local path, query = urllib.parse(url)   
				-- httphandler.on_message(id,code,url,method,header,body)
				if is_static(url) then
					open_file(id,url)
				else
					-- local k,v 
					-- for k,v in ipairs(middle_wares) do
					-- 	if url:find(v.pattern) then
					-- 		local middle_ware = v.middle_ware
					-- 		local code,a,b = sweb.middle_ware(url, method, header, body,root,middle_ware)
					-- 		if code ~=200 then
					-- 			response(id,code,a,b)		
					-- 			socket.close(id)
					-- 			return
					-- 		end
					-- 	end
					-- end
					-- skynet.error(sweb.handle(url, method, header, body,root))
					local header2 = {}
					-- header2["Content-Type"] = "application/json; charset=utf-8"  
					header2["Access-Control-Allow-Origin"] = "*"  
					-- header2["Access-Control-Allow-Methods"] = "POST, GET"  
					-- header2["Access-Control-Allow-Headers"] = "Origin, X-Requested-With, Content-Type, Accept"  
					
					local code2,data2 = sweb.handle(url, method, header, body,root)
					response(id,code2,data2,header2)
				end
			end
		else
			if url == sockethelper.socket_error then
				skynet.error("socket closed")
			else
				skynet.error(url)
			end
		end
		socket.close(id)
	end)
end)
